package org.eclipse.php.internal.console.ui.editor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
import org.eclipse.php.internal.debug.core.launching.PHPProcess;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleListener;
import org.eclipse.ui.console.IOConsoleOutputStream;

public class ProcessCrashDetector implements Runnable, IConsoleListener {

	private ILaunch launch;
	private Process process;
	private ProcessConsole console;
	private PHPExecutableDebuggerInitializer phpExecutableDebuggerInitializer;

	/**
	 * Constructs a process detector on a given {@link Process}.
	 * 
	 * @param launch
	 *            {@link ILaunch}
	 * @param p
	 *            {@link Process}.
	 * @param phpExecutableDebuggerInitializer 
	 */
	public ProcessCrashDetector(ILaunch launch, Process p, PHPExecutableDebuggerInitializer phpExecutableDebuggerInitializer) {
		this.launch = launch;
		this.process = p;
		this.phpExecutableDebuggerInitializer = phpExecutableDebuggerInitializer;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		try {
			StreamGobbler errorGobbler = new StreamGobbler(process
					.getErrorStream(), true);
			StreamGobbler inputGobbler = new StreamGobbler(process
					.getInputStream(), false);

			ConsolePlugin.getDefault().getConsoleManager().addConsoleListener(
					this);

			errorGobbler.start();
			inputGobbler.start();

			int exitValue = process.waitFor();
			IDebugTarget debugTarget = launch.getDebugTarget();
			System.out.println("debugTarget ----------" + debugTarget != null);
			if (debugTarget != null) {
				phpExecutableDebuggerInitializer.notifyAll();
				IProcess p = debugTarget.getProcess();
				if (p instanceof PHPProcess) {
					((PHPProcess) p).setExitValue(exitValue);
				}
			}

		} catch (Throwable t) {
		} finally {
			ConsolePlugin.getDefault().getConsoleManager()
					.removeConsoleListener(this);
		}
	}

	class StreamGobbler extends Thread {
		InputStream is;
		StringBuilder buf;
		boolean isError;
		private IOConsoleOutputStream os;

		StreamGobbler(InputStream is, boolean isError) {
			this.is = is;
			this.buf = new StringBuilder();
			this.isError = isError;
		}

		public void run() {
			try {
				InputStreamReader isr = new InputStreamReader(is);
				BufferedReader br = new BufferedReader(isr);

				String line;
				while ((line = br.readLine()) != null) {
					if (!isError) {
						continue;
					}
					if (console != null) {
						if (os == null) {
							os = console.newOutputStream();
							if (isError) {
								Display.getDefault().syncExec(new Runnable() {
									public void run() {
										os
												.setColor(DebugUIPlugin
														.getPreferenceColor(IDebugPreferenceConstants.CONSOLE_SYS_ERR_COLOR));
									}
								});
							}
						}
						os.write(buf.toString());
						os.write(line + '\n');
						buf.delete(0, buf.length());
					} else {
						buf.append(line).append('\n');
					}
				}
			} catch (IOException ioe) {
				// PHPDebugPlugin.log(ioe);
			} finally {
				if (os != null) {
					try {
						os.close();
					} catch (IOException e) {
						// PHPDebugPlugin.log(e);
					}
				}
			}
		}
	}

	public void consolesAdded(IConsole[] consoles) {
		for (IConsole console : consoles) {
			if (console instanceof ProcessConsole) {
				this.console = (ProcessConsole) console;
			}
		}
	}

	public void consolesRemoved(IConsole[] consoles) {
	}
}
